﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using System.Text;
using System.Collections.Specialized;
using System.Reflection;
using System.Web.Script.Serialization;
using StoryTeller.Domain;
using System.Globalization;
using System.Threading;
using System.Web.Security;

namespace StoryTellerSite.Controllers
{
    public class BaseController : Controller
    {
        public User CurrentUser
        {
            get
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                return (User)serializer.Deserialize(HttpContext.User.Identity.Name, typeof(User));
            }
            set
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                string strJsonUsr = serializer.Serialize(value);
                FormsAuthentication.SetAuthCookie(strJsonUsr, Request.Params["Lembrar"] != null);
                Session["CurrentUser"] = value;
            }
        }

        public ActionResult ChangeLang(string lang, string ReturnUrl)
        {
            CultureInfo culture = new CultureInfo(lang);
            Thread.CurrentThread.CurrentUICulture = culture;
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture.Name);

            this.Session["Culture"] = culture;

            return Redirect(ReturnUrl);

        }

        protected JsonMensagem MessageAfterSubmit
        {
            get { return (TempData["JsonMessageAfterSubmit"] as JsonMensagem); }
            set { TempData["JsonMessageAfterSubmit"] = value; }
        }

        public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext, TempDataDictionary tempData = null)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");
            ViewDataDictionary ViewData = new ViewDataDictionary();
            TempDataDictionary TempData = tempData != null ? tempData : new TempDataDictionary();
            if (model != null)
                ViewData.Model = model;
          
            using (StringWriter sw = new StringWriter())
            {
                try
                {
                    ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                    ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                    viewResult.View.Render(viewContext, sw);
                    return sw.GetStringBuilder().ToString();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        protected void MensagemSubmit(TipoMensagem tipo, Object Model, string NomePartialView, ControllerContext controllerContext)
        {
            this.MessageAfterSubmit = new JsonMensagem(tipo, Model, NomePartialView, controllerContext);
        }

        public JsonResult getMessage()
        {
            if (MessageAfterSubmit != null)
                return MessageAfterSubmit;
            else
                return new JsonResult() { Data = new { Tipo = TipoMensagem.Nenhum } };
        }
    }

    public enum TipoMensagem
    {
        Erro = 0,
        Sucesso = 1,
        Nenhum = 3
    }

    public enum ConfirmButton
    {
        Sim,
        Nao
    }

    public class AjaxDropDown : JsonResult
    {
        public AjaxDropDown(IEnumerable<DropDownItem> DropDownItens)
        {
            StringBuilder sb = new StringBuilder();
            foreach (DropDownItem item in DropDownItens)
            {
                sb.Append("<div SelectedItemAttrId=" + item.Key + " style='margin: 4px;' class='ddlItem' >");
                sb.Append(item.Value);
                sb.Append("</div>");
            }
            this.Data = new { View = sb.ToString() };
        }
    }

    public class JsonTreeView : JsonResult
    {
        string propId;
        string propPai;
        string PropTexto;
        bool collapsed;
        public JsonTreeView(IEnumerable<object> Itens, string NomePropriedadePai, string NomePropriedadeId, string NomePropriedadeTexto, string IdTreeView, bool collapsed = true)
        {
            this.propId = NomePropriedadeId;
            this.propPai = NomePropriedadePai;
            this.PropTexto = NomePropriedadeTexto;

            this.collapsed = collapsed;

            string view = string.Empty;
            IEnumerable<object> Principais = Itens.Where(c => c.GetType().GetProperty(NomePropriedadePai).GetValue(c, null) == null);
            view = "<ul id=\"" + IdTreeView + "\" class=\"Tree\">";
            foreach (var item in Principais)
            {
                view += "<li class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(NomePropriedadeId).GetValue(item, null) + "\" >";
                view += "<span>" + item.GetType().GetProperty(NomePropriedadeTexto).GetValue(item, null) + "</span>";
                view = MontaArvore(view, Itens, item);
                view += "</li>";

            }
            view += "</ul>";

            this.Data = new { TreeView = view, TreeViewId = IdTreeView };
        }

        private string MontaArvore(string UlLi, IEnumerable<object> itens, object Pai)
        {
            IEnumerable<object> Itensfilhos;
            string display;
            List<object> filhos;
            int count;
            HasChild(itens, Pai, out Itensfilhos, out display, out filhos, out count);

            if (count > 0)
            {
                UlLi += string.Format("<ul {0}>", display);

                foreach (var item in filhos)
                {
                    dynamic cat = item;
                    if (Itensfilhos.Where(c => (int)c.GetType().GetProperty(propPai).GetValue(c, null).GetType().GetProperty(propId).GetValue(c, null) == cat.Id).Count() > 0)
                    {
                        HasChild(itens, item, out Itensfilhos, out display, out filhos, out count);
                        object objPai = item.GetType().GetProperty(propPai).GetValue(item, null);
                        int idPai = (int)objPai.GetType().GetProperty(propId).GetValue(objPai, null);

                        if (count == 0)
                            UlLi += "<li CountChildren=\"0\" IdentificadorPai=\" " + idPai + "\" class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(propId).GetValue(item, null) + "\" >";
                        else
                            UlLi += "<li CountChildren=\"1\"  IdentificadorPai=\" " + idPai + "\" class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(propId).GetValue(item, null) + "\" >";

                        UlLi += "<span >" + item.GetType().GetProperty(PropTexto).GetValue(item, null) + "</span>";
                        UlLi = MontaArvore(UlLi, itens, item);
                        UlLi += "</li>";
                    }
                    else
                    {
                        UlLi += "<li class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(propId).GetValue(item, null) + "\" >";
                        UlLi += "<span>" + item.GetType().GetProperty(PropTexto).GetValue(item, null) + "</span>";
                        UlLi += "</li>";
                    }

                }

                UlLi += "</ul>";
            }

            return UlLi;
        }

        private void HasChild(IEnumerable<object> itens, object Pai, out IEnumerable<object> Itensfilhos, out string display, out List<object> filhos, out int count)
        {
            Itensfilhos = itens.Where(c => c.GetType().GetProperty(propPai).GetValue(c, null) != null);

            display = "style=\"display:" + (this.collapsed ? "none\"" : "block\"") + ";";
            var idPai = 0;
            idPai = (int)Pai.GetType().GetProperty(propId).GetValue(Pai, null);
            filhos = new List<object>();

            foreach (var ItemFilho in Itensfilhos)
            {
                dynamic itemPai = ItemFilho.GetType().GetProperty(propPai).GetValue(ItemFilho, null);
                if (itemPai.Id == idPai)
                {
                    filhos.Add(ItemFilho);
                }
            }

            count = filhos.Count();
        }



    }




    public class DropDownItem
    {
        public dynamic Key { get; set; }
        public string Value { get; set; }
    }

    public class JsonMensagem : JsonResult
    {
        public JsonMensagem(TipoMensagem tipoMensagem, Object Model, string NomePartialView, ControllerContext controllerContext, String TituloAlert = "")
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloAlert = "Erro";
            }
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloAlert = "Sucesso";
            }

            this.Data = new { Tipo = (int)tipoMensagem, Titulo = TituloAlert, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }
    }

    public class JsonError : JsonResult
    {
        public JsonError(string NomePartialView, Object Model, ControllerContext controllerContext)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new { Tipo = (int)TipoMensagem.Erro, Titulo = string.Empty, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }
    }

    public class JsonSuccess : JsonResult
    {
        public JsonSuccess(string NomePartialView, Object Model, ControllerContext controllerContext)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new { Tipo = (int)TipoMensagem.Sucesso, Titulo = string.Empty, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }
    }

    public class JsonConfirmComRedirect : JsonResult
    {
        /// <summary>
        /// Confirm sem routeValues no redirecionamento
        /// </summary>
        /// <param name="tipoMensagem"></param>
        /// <param name="Model"></param>
        /// <param name="NomePartialView"></param>
        /// <param name="Controller"></param>
        /// <param name="Action"></param>
        /// <param name="controllerContext"></param>
        /// <param name="TituloConfirm"></param>
        /// <param name="BotaoRedirecionamento"></param>
        public JsonConfirmComRedirect(TipoMensagem tipoMensagem, Object Model, string NomePartialView, String Controller, String Action, ControllerContext controllerContext, String TituloConfirm = "", ConfirmButton BotaoRedirecionamento = ConfirmButton.Nao)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;

            if (string.IsNullOrEmpty(TituloConfirm) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloConfirm = "Erro";
            }
            if (string.IsNullOrEmpty(TituloConfirm) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloConfirm = "Sucesso";
            }

            this.Data = new { UseAlert = false, Sucesso = true, Titulo = TituloConfirm, ConfirmaButton = BotaoRedirecionamento, Tipo = (int)tipoMensagem, Controller = Controller, Action = Action, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }

        /// <summary>
        /// Confirm com routeValues no redirecionamento
        /// </summary>
        /// <param name="tipoMensagem"></param>
        /// <param name="Model"></param>
        /// <param name="NomePartialView"></param>
        /// <param name="Controller"></param>
        /// <param name="Action"></param>
        /// <param name="RouteValues"></param>
        /// <param name="controllerContext"></param>
        /// <param name="TituloConfirm"></param>
        public JsonConfirmComRedirect(TipoMensagem tipoMensagem, Object Model, string NomePartialView, String Controller, String Action, Object RouteValues, ControllerContext controllerContext, String TituloConfirm = "", ConfirmButton BotaoRedirecionamento = ConfirmButton.Nao)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            string queryString = string.Empty;

            if (string.IsNullOrEmpty(TituloConfirm) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloConfirm = "Erro";
            }
            if (string.IsNullOrEmpty(TituloConfirm) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloConfirm = "Sucesso";
            }

            foreach (PropertyInfo item in RouteValues.GetType().GetProperties())
            {
                if (string.IsNullOrEmpty(queryString))
                    queryString = string.Format("?{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
                else
                    queryString += string.Format("&{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
            }

            Action += queryString;

            this.Data = new { UseAlert = false, Titulo = TituloConfirm, ConfirmaButton = BotaoRedirecionamento, Controller = Controller, Action = Action, Tipo = (int)tipoMensagem, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }

    }

    public class JsonMensagemComRedirect : JsonResult
    {
        /// <summary>
        /// Confirm sem routeValues no redirecionamento
        /// </summary>
        /// <param name="tipoMensagem"></param>
        /// <param name="Model"></param>
        /// <param name="NomePartialView"></param>
        /// <param name="Controller"></param>
        /// <param name="Action"></param>
        /// <param name="controllerContext"></param>
        /// <param name="TituloConfirm"></param>
        /// <param name="BotaoRedirecionamento"></param>
        public JsonMensagemComRedirect(TipoMensagem tipoMensagem, Object Model, string NomePartialView, String Controller, String Action, ControllerContext controllerContext, String TituloAlert = "")
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloAlert = "Erro";
            }
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloAlert = "Sucesso";
            }

            this.Data = new { UseAlert = true, Sucesso = true, Titulo = TituloAlert, Tipo = (int)tipoMensagem, Controller = Controller, Action = Action, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }

        /// <summary>
        /// Confirm com routeValues no redirecionamento
        /// </summary>
        /// <param name="tipoMensagem"></param>
        /// <param name="Model"></param>
        /// <param name="NomePartialView"></param>
        /// <param name="Controller"></param>
        /// <param name="Action"></param>
        /// <param name="RouteValues"></param>
        /// <param name="controllerContext"></param>
        /// <param name="TituloConfirm"></param>
        public JsonMensagemComRedirect(TipoMensagem tipoMensagem, Object Model, string NomePartialView, String Controller, String Action, Object RouteValues, ControllerContext controllerContext, String TituloAlert = "")
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            string queryString = string.Empty;

            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloAlert = "Erro";
            }
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloAlert = "Sucesso";
            }

            foreach (PropertyInfo item in RouteValues.GetType().GetProperties())
            {
                if (string.IsNullOrEmpty(queryString))
                    queryString = string.Format("?{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
                else
                    queryString += string.Format("&{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
            }

            Action += queryString;

            this.Data = new { UseAlert = true, Titulo = TituloAlert, Controller = Controller, Action = Action, Tipo = (int)tipoMensagem, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }

    }

    public class JsonRedirect : JsonResult
    {
        public JsonRedirect(String Controller, String Action, ControllerContext controllerContext)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;

            string scheme = String.Format("{0}://", controllerContext.HttpContext.Request.Url.Scheme);
            string u = controllerContext.HttpContext.Request.Url.Authority;
            string url = String.Format("{0}/{1}/{2}/{3}", scheme, u, Controller, Action);
            this.Data = new { RedirectUrl = url };
        }

        public JsonRedirect(String Controller, String Action, Object RouteValues, ControllerContext controllerContext)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;

            string queryString = string.Empty;
            string scheme = String.Format("{0}://", controllerContext.HttpContext.Request.Url.Scheme);
            string u = controllerContext.HttpContext.Request.Url.Authority;
            string url = String.Format("{0}/{1}/{2}/{3}", scheme, u, Controller, Action);

            foreach (PropertyInfo item in RouteValues.GetType().GetProperties())
            {
                if (string.IsNullOrEmpty(queryString))
                    queryString = string.Format("?{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
                else
                    queryString += string.Format("&{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
            }

            url += queryString;

            this.Data = new { RedirectUrl = url };
        }
    }

    public class JsonModal : JsonResult
    {
        public JsonModal(string NomePartialView, Object Model, ControllerContext controllerContext)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new { View = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }
        public JsonModal(string NomePartialView, Object Model, ControllerContext controllerContext, TempDataDictionary TempData)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new { View = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext, TempData) };
        }
    }

    public class JsonPartial : JsonResult
    {
        public JsonPartial(Object ModelRetorno, string ViewRetorno, string SeletorContainerRetorno, bool AppendRetorno, ControllerContext controllerContext)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {

                Tipo = (int)TipoMensagem.Nenhum,
                Container = SeletorContainerRetorno,
                AppendRetorno = AppendRetorno,
                Automatico = true,
                ViewRetorno = BaseController.RenderPartialToString(ViewRetorno, ModelRetorno, controllerContext)
            };
        }

        public JsonPartial(string Partial, string SeletorContainerRetorno, bool AppendRetorno)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                Tipo = (int)TipoMensagem.Nenhum,
                Container = SeletorContainerRetorno,
                AppendRetorno = AppendRetorno,
                Automatico = true,
                ViewRetorno = Partial
            };
        }
    }

    public class JsonMensagemComRetorno : JsonResult
    {
        public JsonMensagemComRetorno(TipoMensagem tipoMensagem, Object ModelMensagem, string ViewMensagem, Object ModelRetorno, string ViewRetorno, ControllerContext controllerContext, String TituloAlert = "")
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloAlert = "Erro";
            }
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloAlert = "Sucesso";
            }

            this.Data = new
            {
                Titulo = TituloAlert,
                Tipo = (int)tipoMensagem,
                ViewMensagem = BaseController.RenderPartialToString(ViewMensagem, ModelMensagem, controllerContext),
                ViewRetorno = BaseController.RenderPartialToString(ViewRetorno, ModelRetorno, controllerContext)
            };

        }

        public JsonMensagemComRetorno(TipoMensagem tipoMensagem, Object ModelMensagem, string ViewMensagem, Object ModelRetorno, string ViewRetorno, string SeletorContainerRetorno, bool AppendRetorno, ControllerContext controllerContext, String TituloAlert = "")
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloAlert = "Erro";
            }
            if (string.IsNullOrEmpty(TituloAlert) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloAlert = "Sucesso";
            }

            this.Data = new
            {
                Titulo = TituloAlert,
                Tipo = (int)tipoMensagem,
                ViewMensagem = BaseController.RenderPartialToString(ViewMensagem, ModelMensagem, controllerContext),
                ViewRetorno = BaseController.RenderPartialToString(ViewRetorno, ModelRetorno, controllerContext),
                Container = SeletorContainerRetorno,
                AppendRetorno = AppendRetorno,
                Automatico = true
            };

        }
    }
}
